/*
 * =====================================================================================
 *
 *       Filename:  main.cpp
 *
 *    Description:  virtual_function
 *
 *        Version:  1.0
 *        Created:  04/17/12 20:11:23
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:   (), 
 *        Company:  NDSL
 *
 * =====================================================================================
 */
#include    <iostream>
using namespace std;
typedef void(*fun)(void);
const int POINTER_LEN = sizeof(int*)/sizeof(int);

class Base
{
    public:
        virtual void f(){ cout<<"Base:f()"<<endl;}
        virtual void g(){ cout<<"Base:g()"<<endl;}
//        virtual void h(){ cout<<"Base:h()"<<endl;}
};

class Drive1:public Base
{
    public:
        virtual void f1(){ cout<<"Drive1:f1()"<<endl;}
        virtual void g1(){ cout<<"Drive1:g1()"<<endl;}
//        virtual void h1(){ cout<<"Drive1:h1()"<<endl;}
};

class Drive2:public Base
{
    public:
        virtual void f(){ cout<<"Drive2:f()"<<endl;}
        virtual void g1(){ cout<<"Drive2:g1()"<<endl;}
//        virtual void h1(){ cout<<"Drive2:h1()"<<endl;}

};


void vir_fun()
{
    Base b;
    fun p_fun = NULL;
    cout<<"virtual function table add:"<<(int*)&b<<endl;
    cout<<"First virtual function in v-table:"<<(int*)*(int*)&b<<endl;
    cout<<"POINTER_LEN:"<<POINTER_LEN<<endl;
    
    p_fun = (fun)*((int*)*(int*)(&b)+0);
    p_fun();
    p_fun = (fun)*((int*)*(int*)(&b)+1*POINTER_LEN);
    p_fun();
    p_fun = (fun)*((int*)*(int*)(&b)+2*POINTER_LEN);
    p_fun();
}

int vir_fun_1(Base& d)
{
    fun p_fun = NULL;
    int i = 0;
    cout<<"virtual function table add:"<<(int*)&d<<endl;
    cout<<"first function in v-table :"<<(int*)*(int*)&d<<endl;

    /*
    do{
        p_fun = (fun)*((int*)*(int*)(&d)+i*POINTER_LEN);
        cout<<"i:"<<i<<endl;
        if (p_fun)  
            p_fun(); 
        else 
            return i;
        i++;
    }while(1);
    */
    /*  */
    p_fun = (fun)*((int*)*(int*)(&d));
    if (p_fun)  p_fun(); else return 0;

    p_fun = (fun)*((int*)*(int*)(&d)+1*POINTER_LEN);
    if (p_fun)  p_fun(); else return 1;

    p_fun = (fun)*((int*)*(int*)(&d)+2*POINTER_LEN);
    if (p_fun)  p_fun(); else return 2;

    p_fun = (fun)*((int*)*(int*)(&d)+3*POINTER_LEN);
    if (p_fun)  p_fun(); else return 3;

    p_fun = (fun)*((int*)*(int*)(&d)+4*POINTER_LEN);
    if (p_fun)  p_fun(); else return 4;

    p_fun = (fun)*((int*)*(int*)(&d)+5*POINTER_LEN);
    if (p_fun)  p_fun(); else return 5;

    p_fun = (fun)*((int*)*(int*)(&d)+6*POINTER_LEN);
    if (p_fun)  p_fun(); else return 6;
    return 6;
}

int main()
{
    int returned = 0;
    //vir_fun();
    Drive1 d1;
    //returned = vir_fun_1(d1);
    cout<<"vir_fun_1 return :"<<returned<<endl;

    Drive2 d2;
    //returned = vir_fun_1(d2);
    cout<<"vir_fun_1 return :"<<returned<<endl;

    Base test;
    //returned = vir_fun_1(test);
    cout<<"vir_fun_1 return :"<<returned<<endl;

    Base* b1 = new Drive1();
    //b1->f1();
}
